/**
 * 
 */
package com.ms.game.db.util;

import java.util.ArrayList;

import org.hibernate.Query;
import org.hibernate.Session;

/**
 * 輕鬆產生 hibernate 的 update query 並執行他
 * <p>
 * <ul>
 * 操作步驟
 * <li>{@link #setSession(Session)}</li>
 * <li>{@link #setTableName(String)}</li>
 * <li>{@link #addSetValue(String, Object)}</li>
 * <li>{@link #setWhereKey(String, Object)}</li>
 * <li>{@link #executeQuery()}</li>
 * </ul>
 * 
 * @author TW15010
 */
public class UpdateQueryBuilder {
	/**
	 * hibernate session
	 */
	private Session session;

	/**
	 * "update" table name
	 */
	private String tableName;

	/**
	 * "set" column list
	 */
	private ArrayList<ColumnValue> columnList = new ArrayList<ColumnValue>();

	/**
	 * "where" key column list, 會用 and 的方式組合起來
	 */
	private ArrayList<ColumnValue> keyColumnList = new ArrayList<ColumnValue>();

	/**
	 * 
	 */
	public UpdateQueryBuilder() {
		super();
	}

	/**
	 * @param session
	 *            hibernate session
	 */
	public UpdateQueryBuilder(Session session) {
		super();
		this.session = session;
	}

	/**
	 * 加入要更新的欄位和數值
	 * 
	 * @param columnName
	 *            欄位名稱
	 * @param value
	 *            數值
	 */
	public void addSetValue(String columnName, Object value) {
		ColumnValue cv = new ColumnValue();

		cv.setName(columnName);
		cv.setValue(value);

		columnList.add(cv);
	}

	/**
	 * 指定 where 的欄位條件
	 * 
	 * @param columnName
	 *            欄位
	 * @param value
	 *            數值
	 */
	public void setWhereKey(String columnName, Object value) {
		keyColumnList.clear();
		addWhereKey(columnName, value);
	}

	/**
	 * 增加其他的 where key, 最後會用 and 的方式組合起來
	 * 
	 * @param columnName
	 *            欄位
	 * @param value
	 *            數值
	 */
	public void addWhereKey(String columnName, Object value) {
		ColumnValue column = new ColumnValue();

		column.setName(columnName);
		column.setValue(value);

		keyColumnList.add(column);
	}

	/**
	 * 產生 hibernate query
	 * 
	 * @return hibernate query
	 */
	public Query createQuery() {
		if (session == null) {
			return null;
		}

		// 命令頭
		StringBuilder sb = new StringBuilder();
		sb.append("update ");
		sb.append(tableName);
		sb.append(" set ");

		// 欄位
		int imax = columnList.size();
		for (int i = 0; i < imax; i++) {
			ColumnValue cv = columnList.get(i);

			if (i > 0) {
				sb.append(", ");
			}

			sb.append(cv.getName() + " = :" + cv.getName());
		}

		sb.append(" where ");

		// where 的欄位
		imax = keyColumnList.size();
		for (int i = 0; i < imax; i++) {
			ColumnValue cv = keyColumnList.get(i);

			if (i > 0) {
				sb.append(" and ");
			}

			sb.append(cv.getName()).append(" = :");
			sb.append('_');
			sb.append(cv.getName());
		}

		Query query = session.createQuery(sb.toString());

		// 要代入的數值

		// 數值欄位
		for (ColumnValue cv : columnList) {
			query.setParameter(cv.getName(), cv.getValue());
		}

		// where key 欄位
		for (ColumnValue cv : keyColumnList) {			
			query.setParameter("_" + cv.getName(), cv.getValue());
		}

		return query;
	}

	/**
	 * 直接執行 query
	 * 
	 * @return
	 */
	public int executeQuery() {
		Query query = createQuery();
		return query.executeUpdate();
	}

	public String getTableName() {
		return tableName;
	}

	/**
	 * 設定要更新的 table 名稱
	 * 
	 * @param tableName
	 *            table name, ex: xxxModel
	 */
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public Session getSession() {
		return session;
	}

	/**
	 * 設定 hibernate 連線 session
	 * 
	 * @param session
	 *            session
	 */
	public void setSession(Session session) {
		this.session = session;
	}
}
